﻿using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.Design;
using System.Web.UI.WebControls;
using System.Reflection;
using System.ComponentModel;
using System.Security;
using System.Security.Permissions;

using PickGold.Util;

namespace PickGold.Web.Controls
{
	/// <summary>
	/// Json 生成器。
	/// </summary>
	//[AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
	//[ParseChildren(false)]
	//[PersistChildren(false)]
	//[Designer(typeof(Designer))]
	[ControlBuilder(typeof(Builder))]
	[ToolboxData("<{0}:Json runat=\"server\" />")]
	public class Json : DataBoundControl, IJson
	{
		class DataSourceReader : IDataReader
		{
			private Json JsonControl;
			private IEnumerable DataEnumerable;
			private IEnumerator DataReader;

			public DataSourceReader(Json json, IEnumerable data)
			{
				this.JsonControl = json;
				this.DataEnumerable = data;
			}

			#region IDataReader

			void IDataReader.Close()
			{
				this.Dispose(false);
			}

			int IDataReader.Depth
			{
				get
				{
					return 0;
				}
			}

			DataTable IDataReader.GetSchemaTable()
			{
				return null;
			}

			bool IDataReader.IsClosed
			{
				get
				{
					if (this.JsonControl == null)
						return true;

					return false;
				}
			}

			bool IDataReader.NextResult()
			{
				return false;
			}

			bool IDataReader.Read()
			{
				return this.Read();
			}

			int IDataReader.RecordsAffected
			{
				get
				{
					return 0;
				}
			}

			void IDisposable.Dispose()
			{
				this.Dispose(true);
			}

			int IDataRecord.FieldCount
			{
				get
				{
					var fs = this.JsonControl.Properties;
					if (fs == null)
						return 0;

					return fs.Length;
				}
			}

			bool IDataRecord.GetBoolean(int i)
			{
				throw new NotImplementedException();
			}

			byte IDataRecord.GetByte(int i)
			{
				throw new NotImplementedException();
			}

			long IDataRecord.GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
			{
				throw new NotImplementedException();
			}

			char IDataRecord.GetChar(int i)
			{
				throw new NotImplementedException();
			}

			long IDataRecord.GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
			{
				throw new NotImplementedException();
			}

			IDataReader IDataRecord.GetData(int i)
			{
				throw new NotImplementedException();
			}

			string IDataRecord.GetDataTypeName(int i)
			{
				throw new NotImplementedException();
			}

			DateTime IDataRecord.GetDateTime(int i)
			{
				throw new NotImplementedException();
			}

			decimal IDataRecord.GetDecimal(int i)
			{
				throw new NotImplementedException();
			}

			double IDataRecord.GetDouble(int i)
			{
				throw new NotImplementedException();
			}

			Type IDataRecord.GetFieldType(int i)
			{
				throw new NotImplementedException();
			}

			float IDataRecord.GetFloat(int i)
			{
				throw new NotImplementedException();
			}

			Guid IDataRecord.GetGuid(int i)
			{
				throw new NotImplementedException();
			}

			short IDataRecord.GetInt16(int i)
			{
				throw new NotImplementedException();
			}

			int IDataRecord.GetInt32(int i)
			{
				throw new NotImplementedException();
			}

			long IDataRecord.GetInt64(int i)
			{
				throw new NotImplementedException();
			}

			string IDataRecord.GetName(int i)
			{
				var fs = this.JsonControl.Properties;
				if (fs != null && fs.Length > i)
					return fs[i];

				return null;
			}

			int IDataRecord.GetOrdinal(string name)
			{
				throw new NotImplementedException();
			}

			string IDataRecord.GetString(int i)
			{
				throw new NotImplementedException();
			}

			object IDataRecord.GetValue(int i)
			{
				return this.GetValue(i);
			}

			int IDataRecord.GetValues(object[] values)
			{
				throw new NotImplementedException();
			}

			bool IDataRecord.IsDBNull(int i)
			{
				throw new NotImplementedException();
			}

			object IDataRecord.this[string name]
			{
				get
				{
					var fs = this.JsonControl.Properties;
					if (fs == null)
						return null;

					for (var i = fs.Length - 1; i >= 0; i--)
					{
						if (string.Compare(fs[i], name, StringComparison.OrdinalIgnoreCase) == 0)
							return this.GetValue(i);
					}

					return null;
				}
			}

			object IDataRecord.this[int i]
			{
				get
				{
					return this.GetValue(i);
				}
			}

			private bool Read()
			{
				if (this.DataReader == null)
				{
					if (this.DataEnumerable == null)
					{
						if (this.JsonControl == null)
							return false;

						this.JsonControl.PerformSelect();
					}
					this.DataReader = this.DataEnumerable.GetEnumerator();
				}
				return this.DataReader.MoveNext();
			}

			private object GetValue(int i)
			{
				if (this.DataReader == null)
				{
					if (this.DataEnumerable == null)
						return null;

					this.DataReader = this.DataEnumerable.GetEnumerator();
				}
				if (this.DataReader == null || this.DataReader.Current == null)
					return null;

				return DataBinder.Eval(this.DataReader.Current, this.JsonControl.Properties[i]);
			}

			private void Dispose(bool disposing)
			{
				this.JsonControl = null;
				this.DataEnumerable = null;
				this.DataReader = null;
			}

			public void SetData(IEnumerable data)
			{
				this.DataEnumerable = data;
			}

			#endregion
		}

		private JsonBuilder _Json;

		/// <summary>
		/// 空对象字符串：{}
		/// </summary>
		public const string EmptyJsonString = JsonBuilder.EmptyJsonString;
		/// <summary>
		/// 空数组字符串：[]
		/// </summary>
		public const string EmptyArrayString = JsonBuilder.EmptyArrayString;
		/// <summary>
		/// 空字符串：null
		/// </summary>
		public const string NullString = JsonBuilder.NullString;
		/// <summary>
		/// 真字符串：null
		/// </summary>
		public const string TrueString = JsonBuilder.TrueString;
		/// <summary>
		/// 假字符串：null
		/// </summary>
		public const string FalseString = JsonBuilder.FalseString;

		/// <summary>
		/// 构造一 Json 对象。
		/// </summary>
		public Json()
		{
			this._Json = new JsonBuilder();
		}

		/// <summary>
		/// 脚本语言。
		/// </summary>
		[DisplayName("脚本语言")]
		[Description("脚本语言")]
		public ScriptLanguage Language { get; set; }

		/// <summary>
		/// 脚本类型。
		/// </summary>
		[DisplayName("脚本类型")]
		[Description("脚本类型")]
		public ScriptType Type { get; set; }

		/// <summary>
		/// 脚本字符集。
		/// </summary>
		[DisplayName("脚本字符集")]
		[Description("脚本字符集")]
		public string Charset { get; set; }

		/// <summary>
		/// 是否延迟加载。
		/// </summary>
		[DisplayName("是否延迟加载")]
		[Description("是否延迟加载")]
		public ScriptDefer Defer { get; set; }

		/// <summary>
		/// 是否生成脚本标签。
		/// </summary>
		[Bindable(true)]
		[DefaultValue(true)]
		[DisplayName("无脚标签")]
		[Description("指示不生成<script></script>标签；仅生成纯脚本代码；")]
		public bool NoTag { get; set; }

		#region Json 成员

		/// <summary>
		/// 添加扩展
		/// </summary>
		/// <param name="name">扩展的成员名称，如果为空(Empty)字符串表示排除扩展列表</param>
		/// <param name="value">扩展的成员值</param>
		public object AppendEP(string name, object value)
		{
			return this._Json.AppendEP(name, value);
		}

		/// <summary>
		/// 添加扩展
		/// </summary>
		/// <param name="key">扩展的对象</param>
		/// <param name="name">扩展的成员名称，如果为空(Empty)字符串表示排除扩展列表</param>
		/// <param name="value">扩展的成员值</param>
		public object AppendEP(object key, string name, object value)
		{
			return this._Json.AppendEP(key, name, value);
		}

		/// <summary>
		/// 类型名称字符串。
		/// </summary>
		[Bindable(true)]
		[DisplayName("类型名称字符串")]
		[Description("类型名称字符串")]
		public string ClassName
		{
			get
			{
				return this._Json.ClassName;
			}
			set
			{
				this._Json.ClassName = value;
			}
		}

		/// <summary>
		/// 变量名。
		/// </summary>
		[Bindable(true)]
		[DisplayName("变量名")]
		[Description("此Json的变量名，建议使用方式：window['????']")]
		public string Variable
		{
			get
			{
				return this._Json.Variable;
			}
			set
			{
				this._Json.Variable = value;
			}
		}

		/// <summary>
		/// 要转换的对象
		/// </summary>
		[Browsable(false)]
		[Bindable(true)]
		[DisplayName("要转换的对象")]
		[Description("要转换的对象")]
		public object Graph
		{
			get
			{
				return this._Json.Graph;
			}
			set
			{
				var json = value as JsonBuilder;
				if (json == null)
				{
					this._Json.Graph = value;
				}
				else
				{
					json.ClassName = this._Json.ClassName;
					json.IgnoreError = this._Json.IgnoreError;
					this._Json = json;
				}
				base.DataSource = null;
				base.DataSourceID = null;
			}
		}
		/// <summary>
		/// 要转换的对象
		/// </summary>
		public object Data
		{
			get
			{
				return this._Json.Data;
			}
			set
			{
				var json = value as JsonBuilder;
				if (json == null)
				{
					this._Json.Data = value;
					return;
				}

				json.ClassName = this._Json.ClassName;
				json.IgnoreError = this._Json.IgnoreError;
				this._Json = json;
			}
		}
		/// <summary>
		/// 要转换的对象
		/// </summary>
		public object Value
		{
			get
			{
				return this._Json.Value;
			}
			set
			{
				var json = value as JsonBuilder;
				if (json == null)
				{
					this._Json.Value = value;
					return;
				}

				json.ClassName = this._Json.ClassName;
				json.IgnoreError = this._Json.IgnoreError;
				this._Json = json;
			}
		}
		/// <summary>
		/// 要转换的对象
		/// </summary>
		public object Source
		{
			get
			{
				return this._Json.Source;
			}
			set
			{
				var json = value as JsonBuilder;
				if (json == null)
				{
					this._Json.Source = value;
					return;
				}

				json.ClassName = this._Json.ClassName;
				json.IgnoreError = this._Json.IgnoreError;
				this._Json = json;
			}
		}
		/// <summary>
		/// 要转换的对象
		/// </summary>
		public object Content
		{
			get
			{
				return this._Json.Content;
			}
			set
			{
				var json = value as JsonBuilder;
				if (json == null)
				{
					this._Json.Content = value;
					return;
				}

				json.ClassName = this._Json.ClassName;
				json.IgnoreError = this._Json.IgnoreError;
				this._Json = json;
			}
		}

		/// <summary>
		/// 忽略错误。
		/// </summary>
		[Bindable(true)]
		[DisplayName("忽略错误")]
		[Description("忽略错误")]
		public bool IgnoreError
		{
			get
			{
				return this._Json.IgnoreError;
			}
			set
			{
				this._Json.IgnoreError = value;
			}
		}

		/// <summary>
		/// 输出属性【字段】列表
		/// </summary>
		[Bindable(true)]
		[DisplayName("输出属性/字段列表")]
		[Description("输出属性/字段列表")]
		[TypeConverter(typeof(StringArrayConverter))]
		//[TypeConverter(typeof(MultilineStringConverter))]
		public string[] Properties
		{
			get
			{
				return this._Json[null, string.Empty] as string[];
			}
			set
			{
				this._Json[null, string.Empty] = value;
			}
		}

		/// <summary>
		/// 尝试获取扩展属性
		/// </summary>
		/// <param name="name">要尝试获取的属性名称</param>
		/// <param name="value">要尝试获取的属性值</param>
		/// <returns>是否获取成功</returns>
		public bool TryGetEP(string name, ref object value)
		{
			return this._Json.TryGetEP(name, ref value);
		}

		/// <summary>
		/// 尝试获取扩展属性
		/// </summary>
		/// <param name="key">要尝试获取属性的对象，如果是【Empty】则表示全局扩展</param>
		/// <param name="name">要尝试获取的属性名称</param>
		/// <param name="value">要尝试获取的属性值</param>
		/// <returns>是否获取成功</returns>
		public bool TryGetEP(object key, string name, ref object value)
		{
			return this._Json.TryGetEP(key, name, ref value);
		}

		/// <summary>
		/// 获取扩展属性
		/// </summary>
		/// <param name="name">要获取的属性名称</param>
		/// <returns>属性值</returns>
		public object GetEP(string name)
		{
			return this._Json.GetEP(name);
		}

		/// <summary>
		/// 设置扩展属性
		/// </summary>
		/// <param name="name">要设置的属性名称，如果为空(Empty)字符串表示排除扩展列表</param>
		/// <param name="value">要设置的属性值</param>
		/// <returns>属性值</returns>
		public object SetEP(string name, object value)
		{
			return this._Json.SetEP(name, value);
		}

		/// <summary>
		/// 获取扩展属性
		/// </summary>
		/// <param name="key">要获取属性的对象，如果是【Empty】则表示全局扩展</param>
		/// <param name="name">要获取的属性名称</param>
		/// <returns>属性值</returns>
		public object GetEP(object key, string name)
		{
			return this._Json.GetEP(key, name);
		}

		/// <summary>
		/// 设置扩展属性
		/// </summary>
		/// <param name="key">要设置属性的对象，如果是【Empty】则表示全局扩展</param>
		/// <param name="name">要设置的属性名称，如果为空(Empty)字符串表示排除扩展列表</param>
		/// <param name="value">要设置的属性值</param>
		/// <returns>属性值</returns>
		public object SetEP(object key, string name, object value)
		{
			return this._Json.SetEP(key, name, value);
		}

		/// <summary>
		/// 移除扩展
		/// </summary>
		public void RemoveEP()
		{
			this._Json.RemoveEP();
		}

		/// <summary>
		/// 移除扩展
		/// </summary>
		/// <param name="key">扩展的对象</param>
		public void RemoveEP(object key)
		{
			this._Json.RemoveEP(key);
		}

		/// <summary>
		/// 移除扩展
		/// </summary>
		/// <param name="key">扩展的对象</param>
		/// <param name="name">扩展的成员名称</param>
		public void RemoveEP(object key, string name)
		{
			this._Json.RemoveEP(key, name);
		}

		/// <summary>
		/// 是否存在扩展
		/// </summary>
		/// <returns></returns>
		public bool HasEP()
		{
			return this._Json.HasEP();
		}

		/// <summary>
		/// 是否存在根对象扩展
		/// </summary>
		/// <param name="name">根对象扩展名</param>
		/// <returns></returns>
		public bool HasEP(string name)
		{
			return this._Json.HasEP(name);
		}

		/// <summary>
		/// 判断指定对象是否存在扩展或存在指定名称的扩展
		/// </summary>
		/// <param name="key">对象</param>
		/// <param name="name">指定对象的名称扩展，如果为空则表示指定对象是否存在任意扩展</param>
		/// <returns></returns>
		public bool HasEP(object key, string name)
		{
			return this._Json.HasEP(key, name);
		}

		/// <summary>
		/// 设置或获取扩展属性
		/// </summary>
		/// <param name="key">要获取或设置属性的对象</param>
		/// <param name="name">要获取或设置的属性名称</param>
		/// <returns>属性值</returns>
		public object this[string name]
		{
			get
			{
				return this._Json[name];
			}
			set
			{
				this._Json[name] = value;
			}
		}

		/// <summary>
		/// 设置或获取扩展属性
		/// </summary>
		/// <param name="key">要获取或设置属性的对象</param>
		/// <param name="name">要获取或设置的属性名称</param>
		/// <returns>属性值</returns>
		public object this[object key, string name]
		{
			get
			{
				return this._Json[key, name];
			}
			set
			{
				this._Json[key, name] = value;
			}
		}

		/// <summary>
		/// 序列化成Json字符串
		/// </summary>
		/// <returns>用Json表示对象的字符串</returns>
		public override string ToString()
		{
			return this._Json.ToString();
			//return base.ToString();
		}

		/// <summary>
		/// 序列化成Json字符串
		/// </summary>
		/// <returns>用Json表示对象的字符串</returns>
		public int Render(TextWriter output)
		{
			return this._Json.Render(output);
		}

		/// <summary>
		/// 输入指定对象的Json字符流
		/// </summary>
		/// <param name="output">Json书写器</param>
		/// <param name="graph">要输出的对象</param>
		/// <param name="stack">防止序列化死递归的堆对象</param>
		/// <param name="path">防止序列化死递归的引用路径</param>
		/// <param name="flags">指示序列化成员的标志</param>
		/// <param name="prefix">前缀字符串</param>
		/// <returns>是否已输出，为零表示没有任何输出，需要生成器继续处理。</returns>
		public virtual int Render(TextWriter output, object graph, IDictionary<object, string> stack, string path, BindingFlags flags, string prefix)
		{
			return this._Json.Render(output, graph, stack, path, flags, prefix);
		}

		/// <summary>
		/// 设置变量名
		/// </summary>
		/// <param name="parent">父变量名，如果为“/”则为“window”对象</param>
		/// <param name="ajax">变量名</param>
		/// <returns>变量名</returns>
		public string SetVariable(string parent, IWebPage ajax)
		{
			if (ajax.Ajax == null)
				return null;

			return WebUtil.SetVariable(this._Json, parent, (ajax.Context.Items.Contains(WebUtil.AJAX_KEY) ? ajax.Context.Items[WebUtil.AJAX_KEY] as string : ajax.Ajax.Name) ?? ajax.Ajax.Name);
		}
		/// <summary>
		/// 设置变量名
		/// </summary>
		/// <param name="parent">父变量名，如果为“/”则为“window”对象</param>
		/// <param name="context">变量名</param>
		/// <returns>变量名</returns>
		public string SetVariable(string parent, HttpContext context)
		{
			if (context == null)
				return null;

			var variable = context.Items[WebUtil.AJAX_KEY] as string;
			if (string.IsNullOrEmpty(variable))
				return null;

			return WebUtil.SetVariable(this._Json, parent, variable);
		}
		/// <summary>
		/// 设置变量名
		/// </summary>
		/// <param name="parent">父变量名，如果为“/”则为“window”对象</param>
		/// <param name="variable">变量名</param>
		/// <returns>变量名</returns>
		public string SetVariable(string parent, string variable)
		{
			return this._Json.SetVariable(parent, variable);
		}
		/// <summary>
		/// 设置变量名
		/// </summary>
		/// <param name="parent">父变量名，如果为“/”则为“window”对象</param>
		/// <param name="var0">变量名，如果为空，则为“var1”的值</param>
		/// <param name="var1">变量名</param>
		/// <returns>变量名</returns>
		public string SetVariable(string parent, string var0, string var1)
		{
			return this._Json.SetVariable(parent, var0, var1);
		}
		/// <summary>
		/// 设置变量名
		/// </summary>
		/// <param name="parent">父变量名，如果为“/”则为“window”对象</param>
		/// <param name="var0">变量名，如果为空，则为“var1”的值</param>
		/// <param name="var1">变量名，如果为空，则为“var2”的值</param>
		/// <param name="var2">变量名</param>
		/// <returns>变量名</returns>
		public string SetVariable(string parent, string var0, string var1, string var2)
		{
			return this._Json.SetVariable(parent, var0, var1, var2);
		}

		/// <summary>
		/// 序列化成Json字符串
		/// </summary>
		/// <param name="staticMember">是否成生静态成员对象</param>
		/// <returns>用Json表示对象的字符串</returns>
		public string ToString(bool staticMember)
		{
			return this._Json.ToString(staticMember);
		}

		/// <summary>
		/// 序列化成Json字符串
		/// </summary>
		/// <param name="bindingFlags">指示序列化成员的标志</param>
		/// <returns>用Json表示对象的字符串</returns>
		public string ToString(BindingFlags bindingFlags)
		{
			return this._Json.ToString(bindingFlags);
		}

		/// <summary>
		/// 序列化成Json字符串
		/// </summary>
		/// <param name="graph">要转换的对象</param>
		/// <returns>用Json表示对象的字符串</returns>
		public static string ToString(object graph)
		{
			return JsonBuilder.ToString(graph);
		}
		/// <summary>
		/// 序列化成Json字符串
		/// </summary>
		/// <param name="graph">要转换的对象</param>
		/// <param name="staticMember">是否成生静态成员对象</param>
		/// <returns>用Json表示对象的字符串</returns>
		public static string ToString(object graph, bool staticMember)
		{
			return JsonBuilder.ToString(graph, staticMember);
		}
		/// <summary>
		/// 序列化成Json字符串
		/// </summary>
		/// <param name="graph">要转换的对象</param>
		/// <param name="bindingFlags">指示序列化成员的标志</param>
		/// <returns>用Json表示对象的字符串</returns>
		public static string ToString(object graph, BindingFlags bindingFlags)
		{
			return JsonBuilder.ToString(graph, bindingFlags);
		}

		/// <summary>
		/// 字符串的JS转义处理
		/// </summary>
		/// <param name="input">输入字符串</param>
		/// <returns>经过JS转义处理后的字符串</returns>
		public static string JsEncode(string input)
		{
			return StringUtil.JsEncode(input);
		}
		/// <summary>
		/// 字符串的JS转义处理
		/// </summary>
		/// <param name="input">输入字符串</param>
		/// <param name="invertedComma">是否使用单引号作为直接字符串常量分界符</param>
		/// <returns>经过JS转义处理后的字符串</returns>
		public static string JsEncode(string input, bool invertedComma)
		{
			return StringUtil.JsEncode(input, invertedComma);
		}
		/// <summary>
		/// 字符串的JS转义处理
		/// </summary>
		/// <param name="input">输入字符串</param>
		/// <param name="stringDivide">直接字符串常量分界符</param>
		/// <returns>经过JS转义处理后的字符串</returns>
		public static string JsEncode(string input, char stringDivide)
		{
			return StringUtil.JsEncode(input, stringDivide);
		}
		/// <summary>
		/// 字符串的JS转义处理
		/// </summary>
		/// <param name="input">输入字符串</param>
		/// <param name="stringDivide">直接字符串常量分界符</param>
		/// <returns>经过JS转义处理后的字符串</returns>
		public static string JsEncode(string input, string stringDivide)
		{
			return StringUtil.JsEncode(input, stringDivide);
		}

		#endregion

		/// <summary>
		/// 获取或设置对象，数据绑定控件从该对象中检索其数据项列表。
		/// </summary>
		[Bindable(true)]
		[DefaultValue("")]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		[Themeable(false)]
		public override object DataSource
		{
			get
			{
				return base.DataSource;
			}
			set
			{
				if (value == null)
					this.Graph = null;
				else
					this.Graph = new DataSourceReader(this, null);
				base.DataSource = value;
			}
		}

		/// <summary>
		/// 获取或设置控件的 ID，数据绑定控件从该控件中检索其数据项列表。
		/// </summary>
		[DefaultValue("")]
		[Themeable(false)]
		[IDReferenceProperty(typeof(DataSourceControl))]
		public override string DataSourceID
		{
			get
			{
				return base.DataSourceID;
			}
			set
			{
				if (value == null)
					this.Graph = null;
				else
					this.Graph = new DataSourceReader(this, null);
				base.DataSourceID = value;
			}
		}

		/// <summary>
		/// 在派生类中重写时，将数据源中的数据绑定到控件。
		/// </summary>
		/// <param name="data">从 System.Web.UI.WebControls.DataBoundControl.PerformSelect() 方法调用返回的数据的 System.Collections.IEnumerable 列表。</param>
		protected override void PerformDataBinding(IEnumerable data)
		{
			var ds = this.GetDataSource();
			if (ds == null)
				return;

			var dr = this.Graph as DataSourceReader;
			if (dr == null)
				this.Graph = new DataSourceReader(this, data ?? Reflector.EmptyEnumerable);
			else
				dr.SetData(data ?? Reflector.EmptyEnumerable);
			dr = null;
		}

		/// <summary>
		/// 将控件的 HTML 开始标记呈现到指定的编写器中。此方法主要由控件开发人员使用。
		/// </summary>
		/// <param name="writer">System.Web.UI.HtmlTextWriter，表示要在客户端呈现 HTML 内容的输出流。</param>
		public override void RenderBeginTag(HtmlTextWriter writer)
		{
			if (this.NoTag)
			{
				//base.RenderBeginTag(writer);
				writer.WriteLine();
				return;
			}

			var language = this.Language;
			var type = this.Type;
			if (type == ScriptType.Unknow && language == ScriptLanguage.Unknow)
				type = ScriptType.JavaScript;
			if (language == ScriptLanguage.Unknow && type != ScriptType.Unknow)
			{
				switch (type)
				{
					case ScriptType.JScript:
						language = ScriptLanguage.JScript;
						break;
					case ScriptType.JavaScript:
						language = ScriptLanguage.JavaScript;
						break;
					case ScriptType.EcmaScript:
						language = ScriptLanguage.EcmaScript;
						break;
					case ScriptType.VbScript:
						language = ScriptLanguage.VbScript;
						break;
					default:
						language = ScriptLanguage.JavaScript;
						type = ScriptType.JavaScript;
						break;
				}
			}
			if (type == ScriptType.Unknow && language != ScriptLanguage.Unknow)
			{
				switch (language)
				{
					case ScriptLanguage.JScript:
						type = ScriptType.JScript;
						break;
					case ScriptLanguage.JavaScript:
						type = ScriptType.JavaScript;
						break;
					case ScriptLanguage.EcmaScript:
						type = ScriptType.EcmaScript;
						break;
					case ScriptLanguage.VbScript:
						type = ScriptType.VbScript;
						break;
					default:
						type = ScriptType.JavaScript;
						language = ScriptLanguage.JavaScript;
						break;
				}
			}
			switch (language)
			{
				case ScriptLanguage.JScript:
					writer.AddAttribute("language", "jscript");
					break;
				case ScriptLanguage.JavaScript:
					writer.AddAttribute("language", "javascript");
					break;
				case ScriptLanguage.EcmaScript:
					writer.AddAttribute("language", "ecmascript");
					break;
				case ScriptLanguage.VbScript:
					writer.AddAttribute("language", "vbscript");
					break;
				default:
					writer.AddAttribute("language", "javascript");
					break;
			}
			switch (type)
			{
				case ScriptType.JScript:
					writer.AddAttribute(HtmlTextWriterAttribute.Type, "text/jscript");
					break;
				case ScriptType.JavaScript:
					writer.AddAttribute(HtmlTextWriterAttribute.Type, "text/javascript");
					break;
				case ScriptType.EcmaScript:
					writer.AddAttribute(HtmlTextWriterAttribute.Type, "text/ecmascript");
					break;
				case ScriptType.VbScript:
					writer.AddAttribute(HtmlTextWriterAttribute.Type, "text/vbscript");
					break;
				default:
					writer.AddAttribute(HtmlTextWriterAttribute.Type, "text/javascript");
					break;
			}
			if (!string.IsNullOrEmpty(this.Charset))
				writer.AddAttribute("charset", this.Charset);
			if (this.Defer == ScriptDefer.Defer)
				writer.AddAttribute("defer", "defer");
			writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID);
			//writer.WriteLine();
			writer.Write("<!--//-->");
			writer.RenderBeginTag(HtmlTextWriterTag.Script);
			writer.WriteLine("<!--<![CDATA[");
		}

		/// <summary>
		/// 将此控件内容发送到提供的 System.Web.UI.HtmlTextWriter 对象，此对象编写将在客户端呈现的内容。
		/// </summary>
		/// <param name="writer">接收控件内容的 System.Web.UI.HtmlTextWriter 对象。</param>
		protected override void Render(HtmlTextWriter writer)
		{
			this.RenderBeginTag(writer);
			if (string.IsNullOrEmpty(this._Json.Variable))
				this._Json.Variable = this.ClientID;
			this._Json.Render(writer);
			this.RenderChildren(writer);
			if (this.NoTag)
				return;

			writer.WriteLine(";");
			writer.Write("//]]>-->");
			writer.RenderEndTag();
			//base.Render(writer);
		}
	}
}
